<template>
  <div>
    <CategorySelector :disabled="!isShowList" />
    <el-card class="attr-card">
      <div v-show="isShowList">
        <el-button
          type="primary"
          icon="el-icon-plus"
          :disabled="!category3Id"
          @click="isShowList = false"
        >添加属性</el-button>
        <el-table
          v-loading="loading"
          class="attr-table"
          :data="attrs"
          border
          style="width: 100%"
        >
          <el-table-column type="index" label="序号" width="50" />
          <el-table-column prop="attrName" label="属性名称" />
          <el-table-column label="属性值列表">
            <template v-slot="{ row }">
              <el-tag
                v-for="valueName in row.attrValueList"
                :key="valueName.id"
                class="attr-tag"
              >{{ valueName.valueName }}</el-tag>
            </template>
          </el-table-column>
          <el-table-column label="操作">
            <template v-slot="{ row }">
              <el-button
                type="warning"
                size="mini"
                icon="el-icon-edit"
                @click="showUpdateAttr(row)"
              />
              <el-button
                type="danger"
                size="mini"
                icon="el-icon-delete"
                @click="delAttr(row)"
              />
            </template>
          </el-table-column>
        </el-table>
      </div>

      <div v-show="!isShowList">
        <el-form inline :rules="rules" :model="attr">
          <el-form-item label="属性名" prop="attrName">
            <el-input v-model="attr.attrName" type="text" />
          </el-form-item>
        </el-form>
        <el-button
          type="primary"
          icon="el-icon-plus"
          :disabled="!attr.attrName"
          @click="showAddAttrValue"
        >添加属性值</el-button>
        <el-table
          v-loading="loading"
          class="attr-table"
          :data="attrValueList"
          border
          style="width: 100%"
        >
          <el-table-column type="index" label="序号" width="50" />
          <el-table-column label="属性值名称">
            <template v-slot="{ row, $index }">
              <el-input
                v-show="row.isEdit"
                :ref="$index"
                v-model="attr.valueName"
                placeholder="请输入属性值名称"
                size="mini"
                @blur="addAttrValue(row)"
                @keyup.enter="addAttrValue(row)"
              />
              <span
                v-show="!row.isEdit"
                style="display: block"
                @click="toEdit(row, $index)"
              >
                {{ row.valueName }}
              </span>
            </template>
          </el-table-column>
          <el-table-column label="操作">
            <template v-slot="{ row, $index }">
              <!-- element-ui文档写错了 onConfirm -->
              <el-popconfirm
                :title="`确定要删除 ${
                  row.valueName ? row.valueName : '空'
                } 属性值吗？`"
                @onConfirm="delAttrValue($index)"
              >
                <!-- 必须使用具名插槽 -->
                <el-button
                  slot="reference"
                  type="danger"
                  size="mini"
                  icon="el-icon-delete"
                />
              </el-popconfirm>
            </template>
          </el-table-column>
        </el-table>
        <el-button type="primary" @click="addAttr">确定</el-button>
        <el-button @click="cancel">取消</el-button>
      </div>
    </el-card>
  </div>
</template>

<script>
import { mapState } from 'vuex'
import { reqGetAttrList, reqSaveAttrInfo, reqDelAttr } from '@api/attr'

export default {
  name: 'Attr',
  data() {
    return {
      attrs: [],
      attrValueList: [], // table遍历显示属性值列表
      loading: false,
      isShowList: true,
      isEdit: false, // 代表是否有进入编辑模式
      // 要收集的属性对象
      attr: {
        // id: 0, // 属性名id
        attrName: '', // 属性名称
        // attrValueList: [], // 属性值列表
        valueName: '' // 单个属性值
      },
      rules: {
        attrName: [
          { required: true, message: '请输入属性名称', trigger: 'blur' }
        ]
      }
    }
  },
  computed: {
    ...mapState({
      // 选中的分类id
      category1Id: (state) => state.category.category1Id,
      category2Id: (state) => state.category.category2Id,
      category3Id: (state) => state.category.category3Id
    })
  },
  watch: {
    // 3Id变化才需要重新请求数据
    async category3Id() {
      try {
        const { category1Id, category2Id, category3Id } = this

        // 如果 category3Id 没有， 不请求数据
        if (!category3Id) {
          this.attrs = []
          return
        }

        const res = await reqGetAttrList({
          category1Id,
          category2Id,
          category3Id
        })

        this.attrs = res.data
      } catch {
        this.$message.error('请求属性列表数据失败~')
      }
    }
  },
  methods: {
    // 显示更新
    showUpdateAttr(row) {
      this.isShowList = false
      // 传递数据
      this.attr.attrName = row.attrName
      this.attr.id = row.id
      this.attrValueList = row.attrValueList
    },
    delAttr(attr) {
      this.$confirm(
        `您确认要删除 <b style="color: red;">${attr.attrName}</b> 品牌数据吗?`,
        '提示',
        {
          dangerouslyUseHTMLString: true, // 让内部代码解析成html
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }
      ).then(async() => {
        this.loading = true
        // 发送请求，删除数据
        await reqDelAttr(attr.id)

        this.$message({
          type: 'success',
          message: '删除属性数据成功!'
        })
        // 更新数据
        const { category1Id, category2Id, category3Id } = this

        const res = await reqGetAttrList({
          category1Id,
          category2Id,
          category3Id
        })

        this.attrs = res.data
        this.loading = false
      })
    },
    // 添加整个属性
    async addAttr() {
      const { attrName, id } = this.attr
      // 判断属性名有值
      if (!attrName) {
        this.$message.warning('请输入属性名')
        return
      }

      const { attrValueList, isEdit } = this
      // 判断编辑模式
      if (isEdit) {
        return
      }
      // 判断属性值至少有一个
      if (attrValueList.length === 0) {
        this.$message.warning('请添加至少一个属性值')
        return
      }

      // 发送请求，添加属性
      /*
        {
          "attrName": "string", // 属性名
          "attrValueList": [ // 属性值列表
            {
              "valueName": "string" // 属性值
            }
          ],
          "categoryId": 0, // 分类id
          "categoryLevel": 0, // 分类等级
        }
      */
      const { category1Id, category2Id, category3Id } = this

      const data = {
        attrName, // 属性名
        attrValueList: attrValueList.map((attr) => {
          return {
            valueName: attr.valueName
          }
        }),
        categoryId: category3Id, // 分类id
        categoryLevel: 3 // 分类等级
      }

      if (id) {
        // 更新
        data.id = id
      }

      try {
        // 添加属性 - 更新服务器数据
        await reqSaveAttrInfo(data)

        this.$message.success(`${id ? '更新' : '添加'}属性成功`)

        // 更新客户端数据
        const res = await reqGetAttrList({
          category1Id,
          category2Id,
          category3Id
        })
        this.attrs = res.data

        // 回到List
        this.cancel()
      } catch (e) {
        console.log(e)
        this.$message.error('添加属性失败')
      }
    },
    // 取消添加属性
    cancel() {
      this.isShowList = true
      // 清空当前数据
      this.attrValueList = []
      this.attr = {
        attrName: '',
        valueName: ''
      }
    },
    // 删除单个属性值
    delAttrValue(index) {
      this.attrValueList.splice(index, 1)
    },
    // 进入编辑模式
    toEdit(row, index) {
      if (this.isEdit) return
      row.isEdit = true
      this.isEdit = true
      this.attr.valueName = row.valueName
      this.$nextTick(() => {
        // 让输入框获取焦点
        this.$refs[index].focus()
      })
    },
    // 添加属性值
    addAttrValue(row) {
      // 值不能为空 也不能重复
      const { valueName } = this.attr
      if (!valueName) {
        this.$message.warning('请输入属性值')
        return
      }

      /*
        初始： [{ valueName: 'aaa' }]
        新增1： [{ valueName: 'aaa' }, { valueName: 'aaa' }]
        新增2： [{ valueName: 'aaa' }]
        如果数组找到两个，就重复了
        如果数组只找到一个，就不重复

        思考：先判断是否重复？在更新数据  - 不好做
      */
      // 当前行有数据显示
      row.valueName = valueName

      // 判断是否重复
      const repeatCount = this.attrValueList.reduce((p, c) => {
        return p + (c.valueName === valueName ? 1 : 0)
      }, 0)

      if (repeatCount > 1) {
        this.$message.warning('输入属性值不能重复')
        return
      }

      // 后面编辑模式不会显示原来的数据
      this.attr.valueName = ''
      // 退出编辑模式
      row.isEdit = false
      this.isEdit = false
    },
    // 显示添加属性值
    showAddAttrValue() {
      if (this.isEdit) return
      // push方法返回值时数组的长度
      const length = this.attrValueList.push({ isEdit: true })
      // 进入了编辑模式
      this.isEdit = true
      // 更新时异步的，要等待DOM元素更新好才行
      this.$nextTick(() => {
        // 让输入框获取焦点
        this.$refs[length - 1].focus()
      })
    }
  }
}
</script>

<style lang="sass" scoped>
.attr-card
  margin: 10px
.attr-table
  margin-top: 20px
  margin-bottom: 20px
.attr-tag
  margin-right: 10px
  margin-bottom: 10px
</style>
